//
//  RecordManager.swift
//  EyeVisionForDoctors
//
//  Created by PMC on 2020/8/18.
//  Copyright © 2020 tao Tao. All rights reserved.
//

import UIKit
import AVFoundation

class RecordManager: NSObject {
    static let sharedInstance = RecordManager()
    var recorder: AVAudioRecorder?
    var player: AVAudioPlayer?
    var playingUrl: String?
    let session = AVAudioSession.sharedInstance()
    let record_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending("/record.caf")
    let mp3_path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending("/record.mp3")
    
    func setSession(type: AVAudioSession.Category) -> Bool {
        let session = AVAudioSession.sharedInstance()
        var result = false

        do{
            try session.setCategory(type)
            result = true
        } catch let err{
            print("设置类型失败:\(err.localizedDescription)")
            result = false
        }
        
        //设置session动作
        do {
            try session.setActive(true)
            result = true
        } catch let err {
            print("初始化动作失败:\(err.localizedDescription)")
            result = false
        }
        
        return result
    }

    func beginRecord() -> Bool {
        var result = false
        
        guard setSession(type: .playAndRecord) else {
            return result
        }

        //录音设置,注意,后面需要转换成NSNumber,如果不转换,你会发现,无法录制音频文件,
        let recordSetting:[String:Any] = [
            AVSampleRateKey : NSNumber(value: 11025),//采样集
            AVFormatIDKey : NSNumber(value: kAudioFormatLinearPCM),//音频格式
            AVLinearPCMBitDepthKey : NSNumber(value: 16),//采样位数
            AVNumberOfChannelsKey : NSNumber(value: 2),//通道数
            AVEncoderAudioQualityKey : NSNumber(value: AVAudioQuality.min.rawValue)//录音质量
        ]
        
        //开始录音
        do {
            let url = URL(fileURLWithPath: record_path ?? "")
            recorder = try AVAudioRecorder(url: url, settings: recordSetting)
            recorder?.isMeteringEnabled = true
            recorder?.prepareToRecord()
            recorder?.record()
            result = true
            print("开始录音")
        } catch let err {
            result = false
            print("录音失败:\(err.localizedDescription)")
        }
        
        return result
    }
    
    //结束录音
    func stopRecord() {
        guard let recorder = recorder else {
            return
        }
        
        if recorder.isRecording {
            print("正在录音,马上结束它,文件保存到了:\(record_path ?? "")")
        }else{
            print("没有录音,但是依然结束它")
        }
        recorder.stop()
        self.recorder = nil
    }
    
    //播放
    func play() {
        do {
            player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: record_path ?? ""))
            print("歌曲长度:\(player!.duration)")
            player?.play()
        } catch let err {
            print("播放失败:\(err.localizedDescription)")
        }
    }
    
    func play(urlStr: String) {
        guard setSession(type: .playback) else {
            HUDTool.showError(message: "播放错误")
            return
        }

        dispatch_queue_global_t.global().async {
            if let url = URL(string: urlStr), let data = try? Data(contentsOf: url){
                dispatch_queue_global_t.main.async {
                    self.play(data: data, urlStr: urlStr)
                }
            } else {
                dispatch_queue_global_t.main.async {
                    HUDTool.showError(message: "播放错误")
                }
            }
        }
    }
    
    func play(data: Data, urlStr: String)  {
        do {
            player = try AVAudioPlayer(data: data)
            player?.delegate = self
            print("歌曲长度:\(player?.duration ?? 0.00)")
            playingUrl = urlStr
            NotificationCenter.default.post(name: NotiName.audioPlayBegin, object: self.playingUrl)
            player?.play()
        } catch let err {
            print("播放失败:\(err.localizedDescription)")
            HUDTool.show(message: "播放错误")
        }
    }
    
    func stopPlay() {
        if let player = self.player {
            if player.isPlaying {
                print("正在播放,马上结束它")
            }else{
                print("没有播放,但是依然结束它")
            }
            NotificationCenter.default.post(name: NotiName.audioPlayEnd, object: playingUrl)
            player.stop()
            playingUrl = nil
            self.player = nil
        }else{
            print("没有初始化")
        }
    }
    
    func pausePlay() {
        if let player = self.player {
            if player.isPlaying {
                print("正在播放,马上暂停它")
            }else{
                print("没有播放,但是依然暂停它")
            }
            player.pause()
        }else{
            print("没有初始化")
        }
    }
}

extension RecordManager: AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        NotificationCenter.default.post(name: NotiName.audioPlayEnd, object: playingUrl)
        playingUrl = nil
        print("audio play finish")
    }
    func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
        NotificationCenter.default.post(name: NotiName.audioPlayEnd, object: playingUrl)
        playingUrl = nil
        print("audio play DecodeError")
    }
}

extension RecordManager {
    func getAudioTime(path: String?) -> Double? {
        do {
            player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path ?? ""))
            print("歌曲长度:\(player?.duration ?? 0.0)")
            return player?.duration
        } catch let err {
            print("长度获取失败:\(err.localizedDescription)")
            return nil
        }
    }
}

extension RecordManager {
    func requestAuthorizations(finish: @escaping (_ granted: Bool) -> Void) {
        AVAudioSession.authorizeToMicrophone { granted in
            finish(granted)
        }
    }

    //获取Document路径
    class func getDocumentPath() -> String {
        let filePaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        return filePaths.first!+"/"
    }


    //获取文件夹下文件列表
    class func getFileListInFolderWithPath(path: String) -> Array<String> {
        let fileManager = FileManager.default
        let fileList = try! fileManager.contentsOfDirectory(atPath: path)
        return fileList
    }

    //获取Documents目录下的所有文件
    class func getDomcumentAllFolder() -> Array<String> {
        let paths = self.getDocumentPath()
        let fileManager = FileManager.default
        let fileList = try! fileManager.contentsOfDirectory(atPath: paths)
        var isDir: ObjCBool = false
        var dirArray = Array<String>()
        for fileName in fileList {
           let path = paths+fileName
           if fileManager.fileExists(atPath: path, isDirectory: &isDir) {
               if !isDir.boolValue {
                   dirArray.append(fileName)
               }
           }
        }
        return dirArray
    }

    //查看文件夹是否存在
    class func isJudgeFileOrFolderExists(folderName: String) -> Bool{
        let fileManager = FileManager.default
        let exist = fileManager.fileExists(atPath: folderName)
        if (exist) {
           return true
        }else{
           return false
        }
    }

    //创建目录
    class func createFolderInDocumentObjects(fileName: String) -> Bool{
        if fileName != ""{
           let paths = self.getDocumentPath()
           let userDirectory = paths + fileName
           let fileManager = FileManager.default
           if(!fileManager.fileExists(atPath: userDirectory)){
               try! fileManager.createDirectory(atPath: userDirectory, withIntermediateDirectories: false, attributes: nil)
               return true
           }
        }
        return false
    }

    //移除文件
    class func removefile(folderName: String){ 
        if folderName == ""{
           return
        }
        let fileManager = FileManager.default
        do {
            try fileManager.removeItem(atPath: folderName)
        } catch {
            print(error)
        }
    }

    //移除文件夹下所有文件
    class func deleteFileAtPath(folderName: String){
        let paths = self.getDocumentPath()
        let folderDirectory = paths + folderName
        let fileManager = FileManager.default
        let enmerator = fileManager.enumerator(atPath: folderDirectory)
        for fileName in enmerator! {
           let filePath = folderDirectory.appendingFormat("\(fileName)")
           try! fileManager.removeItem(atPath: filePath)
        }
    }

    //获取文件创建时间
    class func getFileCreateTime(filePath:String)->String {
        let fileManager = FileManager.default
        let attributes = try! fileManager.attributesOfItem(atPath: filePath)
        return String(describing: attributes[FileAttributeKey.creationDate]!)
    }

    //获取文件大小
    class func getFileSize(folderPath: String)-> String{
        if folderPath.count == 0 {
           return "0MB" as String
        }
        let manager = FileManager.default
        if !manager.fileExists(atPath: folderPath){
           return "0MB" as String
        }
        var fileSize:Float = 0.0
        do {
           let files = try manager.contentsOfDirectory(atPath: folderPath)
           
           for file in files {
               let path = folderPath + file
               fileSize = fileSize + fileSizeAtPath(filePath: path)
           }
        }catch{
           fileSize = fileSize + fileSizeAtPath(filePath: folderPath)
        }

        var resultSize = ""
        if fileSize >= 1024.0*1024.0{
           resultSize = NSString(format: "%.2fMB", fileSize/(1024.0 * 1024.0)) as String
        }else if fileSize >= 1024.0{
           resultSize = NSString(format: "%.fkb", fileSize/(1024.0 )) as String
        }else{
           resultSize = NSString(format: "%llub", fileSize) as String
        }

        return resultSize
    }

    //计算单个文件或文件夹的大小
    class func fileSizeAtPath(filePath:String) -> Float {
        let manager = FileManager.default
        var fileSize:Float = 0.0
        if manager.fileExists(atPath: filePath) {
           do {
               let attributes = try manager.attributesOfItem(atPath: filePath)
               if attributes.count != 0 {
                   fileSize = attributes[FileAttributeKey.size]! as! Float
               }
           }catch{
           }
        }
        return fileSize;
    }
}
